﻿using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Management;
using System.Drawing.Printing;
using System.Configuration;
using System.Timers;
using System.Diagnostics;

namespace DisplayManager
{
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public struct PHYSICAL_MONITOR
    {
        public IntPtr hPhysicalMonitor;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        public string szPhysicalMonitorDescription;
    }

    class Program
    {
        [DllImport("shell32.dll", CharSet = CharSet.Auto)]
        public static extern int SHQueryUserNotificationState(out int qns);

        [DllImport("user32.dll", EntryPoint = "MonitorFromWindow")]
        public static extern IntPtr MonitorFromWindow([In] IntPtr hwnd, uint dwFlags);
        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern IntPtr GetForegroundWindow();
        [DllImport("user32.dll")]
        private static extern bool GetWindowText(IntPtr hWnd, StringBuilder title, int maxBufSize);
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private extern static int GetWindowTextLength(IntPtr hWnd);

        [DllImport("dxva2.dll", EntryPoint = "GetNumberOfPhysicalMonitorsFromHMONITOR")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool GetNumberOfPhysicalMonitorsFromHMONITOR(IntPtr hMonitor, ref uint pdwNumberOfPhysicalMonitors);
        [DllImport("dxva2.dll", EntryPoint = "GetPhysicalMonitorsFromHMONITOR")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool GetPhysicalMonitorsFromHMONITOR(IntPtr hMonitor, uint dwPhysicalMonitorArraySize, [Out] PHYSICAL_MONITOR[] pPhysicalMonitorArray);
        [DllImport("dxva2.dll", EntryPoint = "SetMonitorBrightness", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool SetMonitorBrightness(IntPtr hMonitor, short brightness);

        [DllImport("dxva2.dll", EntryPoint = "GetMonitorBrightness", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool GetMonitorBrightness(IntPtr hMonitor, ref short pdwMinimumBrightness, ref short pdwCurrentBrightness, ref short pdwMaximumBrightnes);

        private static PHYSICAL_MONITOR[] _physicalMonitorArray;
        private static uint _physicalMonitorsCount = 0;
        private static short current = -1, minimum = -1, maximum = -1;
        private static string currentKey = "";


        static void Main(string[] args)
        {
            GetPhysicalMonitors();
            var appSettings = ConfigurationManager.AppSettings;
            if (appSettings.Count == 0)
            {
                Console.WriteLine("AppSettings is empty.");
            }
            else
            {
                Console.WriteLine("currentBrightness" + current);
            }
            var timer = new Timer(5000)
            {
                AutoReset = true,
                Enabled = true
            };
            timer.Elapsed += new ElapsedEventHandler(QuertState);

            Console.ReadLine();
        }

        private static void QuertState(object sender, EventArgs e)
        {            
            int state;
            SHQueryUserNotificationState(out state);
            Console.WriteLine(state);
            string key = "";
            if (state == 2)
            {
                key = "fullscreen";
            }
            else
            {
                key = GetForegroundProcessPath();
            }
            if(!currentKey.Equals(key))
            {
                currentKey = key;
                GetBrightness();
            }
            var appSettings = ConfigurationManager.AppSettings;

            short targetBrightness;
            if (appSettings.GetValues(key) != null)
            {
                targetBrightness= short.Parse(appSettings.GetValues(key)[0]);
            }
            else
            {
                targetBrightness = short.Parse(appSettings.GetValues("default")[0]);
            }
            Console.WriteLine("state:" + state);
            Console.WriteLine("ForegroundProcessPath:" + key);
            Console.WriteLine("currentBrightness:"+ current);
            Console.WriteLine("targetBrightness:" + targetBrightness);
            if (current != targetBrightness)
            {
                SetBrightness(targetBrightness);
                current = targetBrightness;
            }
        }

        public static void SetBrightness(short brightness)
        {            
            foreach (var _physicalMonitor in _physicalMonitorArray)
            {
                SetMonitorBrightness(_physicalMonitor.hPhysicalMonitor, brightness);
            }            
        }

        public static void GetPhysicalMonitors()
        {
            IntPtr myPtr = GetForegroundWindow();

            IntPtr ptr = MonitorFromWindow(myPtr, 0u);
            if (!GetNumberOfPhysicalMonitorsFromHMONITOR(ptr, ref _physicalMonitorsCount))
            {
                throw new Exception("Cannot get monitor count!");
            }
            //Console.WriteLine("_physicalMonitorsCount" + _physicalMonitorsCount);
            _physicalMonitorArray = new PHYSICAL_MONITOR[_physicalMonitorsCount];

            if (!GetPhysicalMonitorsFromHMONITOR(ptr, _physicalMonitorsCount, _physicalMonitorArray))
            {
                throw new Exception("Cannot get phisical monitor handle!");
            }
        }

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int GetWindowThreadProcessId(IntPtr handle, out uint processId);

        public static string GetForegroundProcessPath()
        {
            IntPtr hwnd = GetForegroundWindow();
            uint pid = 0;
            GetWindowThreadProcessId(hwnd, out pid);
            Process proc = Process.GetProcessById((int)pid);
            try
            {
                return proc.MainModule.FileName.ToString();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
                
                return "";
            }
            
        }

        public static short GetBrightness()
        {
            GetMonitorBrightness(_physicalMonitorArray[0].hPhysicalMonitor, ref minimum, ref current, ref maximum);
            Console.WriteLine("minimum:"+ minimum);
            Console.WriteLine("current:" + current);
            Console.WriteLine("maximum:" + maximum);
            return current;
        }
    }
}
